home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / cool.lha / ice / CCC / CCC.c < prev    next >
C/C++ Source or Header  |  1991-09-04  |  55KB  |  1,953 lines

  1. /*
  2.  
  3.  
  4.  Copyright (C) 1990 Texas Instruments Incorporated.
  5.  
  6.  Permission is granted to any individual or institution to use, copy, modify,
  7.  and distribute this software, provided that this complete copyright and
  8.  permission notice is maintained, intact, in all copies and supporting
  9.  documentation.
  10.  
  11.  Texas Instruments Incorporated provides this software "as is" without
  12.  express or implied warranty.
  13.  
  14.  
  15.  * 
  16.  * C++ compiler driver
  17.  *
  18.      CCC (capital CCC) translates C++ source code to C source code.
  19.      The command uses cpp(1) for preprocessing, cfront for syntax
  20.      and type checking, and cc(1) for code generation.
  21.  
  22.      CCC assumes arguments ending in
  23.  
  24.      .c   are C++ source programs; they are  compiled,  and  each
  25.           object  program  is left on the file whose name is that
  26.           of the source with .o substituted for .c.
  27.  
  28.      .s   are assembly source programs; they are  assembled  into
  29.           .o files.
  30.  
  31.      CCC interprets the following options:
  32.  
  33.      -n   Print what would have been done, but don't do it.
  34.  
  35.      -v   Verbose mode.  Print the commands as they are called.
  36.  
  37.      -c   Suppress linking with ld(1) and produce a .o  file
  38.           for each source file.  A single object file can be
  39.           named explicitly using the -o option.
  40.  
  41.      -C   Prevent cpp and cfront from removing comments.
  42.  
  43.      -E   Run only cpp on the .c files and  send  the  result  to
  44.           standard output.
  45.  
  46.      -F   Run only cpp and cfront on the .c files  and  send  the
  47.           result to standard output.
  48.  
  49.      -Fc  Like the -F option, but the output  is  C  source  code
  50.           suitable as a .c file for cc(1).
  51.  
  52.      -.suffix
  53.           Instead of using standard output for the -E , -F or -Fc
  54.           options,  place  the output from each .c file on a file
  55.           with the corresponding .suffix.
  56.  
  57.      -k   Keep the files __ctdt.c and __ctdt.o.  They are used to
  58.           initialize  global  and static class objects.  Normally
  59.           they are removed.
  60.  
  61.      -NOMUNCH
  62.      -NOPATCH
  63.           Do not run munch or patch on the resulting  object  file.
  64.           This  phase  is  normally  needed to detect static con-
  65.           structors and destructors.
  66.  
  67.      -x1  cpp debug print of files #included
  68.      -x2  cpp debug inserts #control as comments in output
  69.      -x3  cpp debug does both -x1 and -x2
  70.  
  71.      +d   Suppress expansion of inline functions.
  72.  
  73.      +e1,+e0
  74.           These flags affect how the compiler handles tables  for
  75.           virtual  functions.  +e1 causes the tables to be exter-
  76.           nal and initialized; +e0 causes the tables to be exter-
  77.           nal  and  uninitialized.   If neither flag is specified
  78.           (the default), the tables are local (static)  and  ini-
  79.           tialized. One file with all virtuals known to it should
  80.           be compiled with +e1; the rest should be compiled  with
  81.           +e0.   Having  one  external  table  may  significantly
  82.           reduce compile time, link time and object file size.
  83.  
  84.      +i   Keep C source code produced by the front end in  a  ..c
  85.           file.  Line number information is stripped.
  86.  
  87.      +V   Accept  regular  C  function  declarations;   use   the
  88.           /usr/include directory for #include files.  Support for
  89.           this option is not guaranteed in future releases
  90.  
  91.      +L   Generate source line number information using the  for-
  92.           mat "#line %d" instead of "#%d".
  93.  
  94.      +xfile
  95.           Read a file of sizes and alignments. Each line contains
  96.           three fields: a type name, the size (in bytes), and the
  97.           alignment (in bytes). This option is useful  for  cross
  98.           compilation.
  99.  
  100.      +S   Spy on cfront;  that  is,  print  some  information  on
  101.           stderr.
  102.  
  103.      +Z30000 Set cfront lex input buffer size
  104.  
  105.      +zf127  Set number of files that can be concurrently opened in cfront
  106.  
  107.      -???
  108.           All other - flags are sent to the "C" compiler
  109.  
  110.      /???
  111.           All /xxx flags are sent to the linker
  112.  
  113.      +???
  114.           All +xxx flalgs are sent to cfront
  115.  
  116.      If the environment variable INCLUDE exists, it is assumed to be a
  117.      colon separated list of directories to be searched when trying to
  118.      find '#include' files.  This is an alternative to the -I flag of
  119.      cc(1).
  120.  
  121.      If set, the environment variables ccpC (preprocessor), cfrontC (C++
  122.      front end), ccC (c compiler), assemblerC (assembler), linkerC
  123.      (linker), and LIBRARY (C++ library) override the defaults.
  124.  
  125.      See ld(1) for loader options, as(1) for assembler options, cc(1)
  126.      for code generation options, and cpp(1) for preprocessor options.
  127.  */
  128.  
  129. /* exit status codes
  130.  * 2    too many errors
  131.  * 1    internal error
  132.  * 0    all went well
  133.  * -1   nothing done
  134.  */
  135.  
  136. #if defined(MSDOS) && !defined(DOS) /* Lets us work with IBM or MS compilers */
  137. #define DOS
  138. #endif
  139.  
  140. #include <ctype.h>
  141. #include <stdio.h>
  142. #include <string.h>
  143. #include <signal.h>
  144. #include <fcntl.h>
  145.  
  146. #if defined(DOS)
  147. #include <process.h>
  148. #else
  149. #include <sys/types.h>
  150. #include <sys/file.h>
  151. #endif
  152.  
  153. #include "config.h"
  154.  
  155. #define nil 0
  156. #define EOL '\0'
  157.  
  158. typedef char *String;
  159. typedef char **StringVec;
  160. typedef int FileDesc;
  161. typedef enum {false, true} boolean;
  162.  
  163. #define BADEXEC -1
  164.  
  165. #define IsChild(pid) ((pid)==0)
  166.  
  167. #define stdinDesc       0
  168. #define stdoutDesc      1
  169.  
  170. static String PREPROCESSOR;
  171. static String CCfrontEnd;
  172. static String Ccompiler;
  173. static String ASSEMBLER;
  174. static String LINKER;
  175. static String MUNCHER;
  176. static String PATCHER;
  177. static String COMPRESS;
  178. static String MV;
  179. static String LIB;
  180. static String StdCClib;
  181. static String frontEndSuffix;
  182. static String runtimeLib;
  183. static String cclib;
  184. static String TMPDIR;
  185.  
  186. static String ENVPATH = "INCLUDE=";
  187. static String DEFAULTLINKER = CC_ld;
  188. static String INCLINK = "inclink";
  189. static String RELINK = "relink";
  190.  
  191. #define ARGSIZE         2048
  192. #define FILENAMESIZE    256
  193. #define MAXARGS         128
  194. #define MAXTMPFILES     64
  195. #define PATHLEN         1024
  196. #define SET             true
  197.  
  198. boolean Cflag = false;
  199. boolean Eflag = false;
  200. boolean Fflag = false;
  201. boolean FcFlag = false;
  202. boolean plusIflag = false;
  203. boolean suffixFlag = false;
  204. boolean verboseFlag = false;
  205. boolean fakeFlag = false;
  206. boolean objFlag = false;
  207. boolean ignErrFlag = false;
  208. boolean skipAsmFlag = false;
  209. boolean cFlag = false;
  210. boolean noMunchFlag = false;
  211. boolean gFlag = false;
  212. boolean gprofFlag = false;
  213. boolean profFlag = false;
  214. boolean genRelocInfoFlag = false;
  215. boolean keepctdtFlag = false;
  216. boolean implementQuick = false;
  217.  
  218. boolean translator;              /* true if generates C code */
  219. boolean dotdotsuffix;              /* true if ..c suffix */
  220.  
  221. boolean ccIsLinker;              /* true if using cc for link phase */
  222.  
  223. String cppArgs[MAXARGS];
  224. StringVec cppArgv = cppArgs;
  225.  
  226. String cppPathArgs[MAXARGS];
  227. StringVec cppPathv = cppPathArgs;
  228.  
  229. String ccArgs[MAXARGS];
  230. StringVec ccArgv = &ccArgs[0];
  231.  
  232. String frontEndArgs[MAXARGS];
  233. StringVec frontEndArgv = frontEndArgs;
  234.  
  235. String linkArgs[MAXARGS];                 /* Link options */
  236. StringVec linkArgv = linkArgs;
  237.  
  238. String linkObjs[MAXARGS];                 /* Objects to link */
  239. StringVec linkObjv = linkObjs;
  240.  
  241. String linkLibs[MAXARGS];                 /* Link Libraries */
  242. StringVec linkLibv = linkLibs;
  243.  
  244. String commandv[MAXARGS];
  245. StringVec command;
  246.  
  247. String objSpaceArgs[MAXARGS];
  248. StringVec objSpaceArgv = &objSpaceArgs[0];
  249.  
  250. String implementArgs[MAXARGS];
  251. StringVec implementArgv = &implementArgs[0];
  252.  
  253. char implement_count[20];
  254.  
  255. char tmpFilesList[MAXTMPFILES][FILENAMESIZE];
  256. char xBuff[FILENAMESIZE];          /* for +x file flag */
  257. int tmpFileCount = 0;
  258.  
  259. extern StringVec environ;
  260.  
  261. char libDirBuff[128] = CC_libdir;
  262. static String libDir = libDirBuff;
  263.  
  264. char fileName[FILENAMESIZE];              /* Temporary */
  265. char cppName[FILENAMESIZE];               /* Name of cpp output file */
  266. char frontEndName[FILENAMESIZE];
  267. char compressName[FILENAMESIZE];
  268. char filterName[FILENAMESIZE];
  269. char destname[FILENAMESIZE];
  270. char objName[FILENAMESIZE];
  271. char libPath[FILENAMESIZE];
  272. char implementName[FILENAMESIZE];         /* Name of implement input file */
  273. char lastLib[FILENAMESIZE];               /* last -l file file */
  274. char ccPath[PATHLEN];
  275. String myname, linkFile;
  276. String suffix;
  277.  
  278. int cppDesc, dest;
  279. int numErrors = 0;
  280.  
  281. void Error (msg1, msg2)
  282. String msg1, msg2;
  283. {
  284.     if (msg2 == nil || *msg2 == EOL) {
  285.         fprintf(stderr, "%s: %s\n", myname, msg1);
  286.     } else {
  287.         fprintf(stderr, "%s: %s %s\n", myname, msg1, msg2);
  288.     }
  289.     exit(1);
  290. }  /* Error */
  291.  
  292. void WarningMsg (msg1, msg2)
  293. String msg1, msg2;
  294. {
  295.     if (msg2 == nil || *msg2 == EOL) {
  296.         fprintf(stderr, "%s: %s\n", myname, msg1);
  297.     } else {
  298.         fprintf(stderr, "%s: %s %s\n", myname, msg1, msg2);
  299.     }
  300. }  /* WarningMsg */
  301.  
  302. int Rename (old, new)
  303. String old; 
  304. String new;
  305. {
  306.   if (verboseFlag) {
  307.     fprintf(stderr, "mv %s %s\n", old, new);
  308.   }
  309. #if defined(M_XENIX)
  310.   link(old, new);              /* Xenix doesn't have rename */
  311.   return unlink(old);
  312. #else
  313.   return rename(old, new);
  314. #endif
  315. }  /* Rename */
  316.  
  317. void Remove (file)
  318. String file; 
  319. {
  320.   int i;
  321.  
  322.   if (keepctdtFlag == false && fakeFlag == false 
  323.          && file != nil && *file != EOL) {
  324.     if (verboseFlag) {
  325.       fprintf(stderr, "rm %s\n", file);
  326.     }
  327.     unlink(file);              /* Delete the file */
  328.   }
  329.                                           /* Remove file from temporary list */
  330.   for (i=0; i<tmpFileCount; i++)
  331.     if (strcmp(tmpFilesList[i], file) == 0) {
  332.       tmpFilesList[i][0] = EOL;
  333.       if ((i+1) == tmpFileCount) tmpFileCount--;
  334.       break;
  335.     }
  336. }  /* Remove */
  337.  
  338. void RemoveTmpFiles ()
  339. {
  340.   int i;
  341.   for (i=0; i<tmpFileCount; i++) {
  342.     if (tmpFilesList[i][0] != EOL)
  343.       Remove(tmpFilesList[i]);
  344.   }
  345.   tmpFileCount = 0;
  346. }  /* RemoveTmpFiles */
  347.  
  348. void Quit (exitStatus)
  349. int exitStatus;
  350. {
  351.     RemoveTmpFiles();
  352.     exit(exitStatus);
  353. }  /* Quit */
  354.  
  355. void myclose (desc)
  356. FileDesc desc;
  357. {
  358.     if (fakeFlag == false && close(desc) != 0) {
  359.         fprintf(stderr, "(%d) ", desc);
  360.         perror("CCC: close failed");
  361.     }
  362. }  /* myclose */
  363.  
  364. FileDesc myopen (filename, flags, mode)
  365. String filename;
  366. int flags, mode;
  367. {
  368.     int f;
  369.     if (fakeFlag == false) {
  370.         f = open(filename, flags, mode);
  371.         if (f < 0) {
  372.             fprintf(stderr, "(%s) ", filename);
  373.             perror("CCC: open failed");
  374.             Quit(1);
  375.         }
  376.     } else
  377.         f = -1;
  378.     return f;
  379. }  /* myopen */
  380.  
  381. /*
  382.  * Add an argument to the end of an argument list
  383.  */
  384. StringVec AddArg (l, s)
  385.     StringVec l;
  386.     String s;
  387. {
  388.   if (s != 0 && *s != EOL) {
  389.     *l++ = s;
  390.   }
  391.   return l;
  392. }  /* AddArg */
  393.  
  394. /*
  395.  * Append a list of arguments to the end of an argument list
  396.  * Input is a space-seperated list of arguments
  397.  */
  398. StringVec AddArgs(l, s)
  399.     StringVec l;
  400.     String s;
  401. {
  402.   String p = s;
  403.   for(;;) {
  404.     if (isspace(*p) || *p == EOL) {
  405.       int len = p-s;
  406.       if (len > 0) {
  407.         String r = (String) malloc(len+1);
  408.         strncpy(r, s, len);
  409.         *(r+len) = EOL;
  410.         l = AddArg(l, r);
  411.       }
  412.       if (*p == EOL) break;
  413.       while(isspace(*(p+1))) p++;
  414.       s = p+1;
  415.     }
  416.     if (*p++ == EOL) break;
  417.   }
  418.   return l;
  419. }  /* AddArgs */
  420.  
  421. /*
  422.  * Append a list of arguments to the end of an argument list
  423.  */
  424. StringVec AddList (v, list)
  425.     StringVec v;
  426.     StringVec list;
  427. {
  428.   if (list == 0 || *list == EOL) {
  429.     /*  fprintf(stderr, "%s: AddList: null string\n", myname); */
  430.   } else {
  431.     while (*list != 0) {
  432.       *v++ = *list++;
  433.     }
  434.   }
  435.   return v;
  436. }  /* AddList */
  437.  
  438. String newString (s)
  439. String s;
  440. {
  441.      String p;
  442.      p = (char*) malloc(FILENAMESIZE);
  443.      strcpy(p, s);
  444.      return p;
  445. }  /* newString */
  446.  
  447. void RegisterTmpFile (filename)
  448. String filename;
  449. {
  450.     int i;
  451.  
  452.     if (tmpFileCount >= MAXTMPFILES) {
  453.         for (i = 0; i<MAXTMPFILES ; i++) {
  454.             unlink(tmpFilesList[i]);
  455.             tmpFilesList[i][0] = EOL;
  456.         }
  457.         tmpFileCount = 0;
  458.     }
  459.     strcpy(tmpFilesList[tmpFileCount], filename);
  460.     tmpFileCount++;
  461. }  /* RegisterTmpFile */
  462.  
  463. TmpFileName(tmpname, characteristic, type)
  464.     String tmpname;
  465.     String characteristic;
  466.     String type;
  467. {
  468.  sprintf(tmpname, "%sC%d%s.%s", TMPDIR, getpid() % 9999, characteristic, type);
  469.  RegisterTmpFile(tmpname);
  470. }  /* TmpFileName */
  471.  
  472. FileDesc MakeTmpFile (tmpname, characteristic, type)
  473.     String tmpname;
  474.     String characteristic;
  475.     String type;
  476. {
  477.   int t;
  478.   TmpFileName(tmpname, characteristic, type);
  479.   if (fakeFlag == false) {
  480.     t = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  481.     if (t < 1) {
  482.       perror("CCC: cannot open tmp file");
  483.       exit(1);
  484.     }
  485.   } else {
  486.     t = stdoutDesc;
  487.   }
  488.   return t;
  489. }  /* MakeTmpFile */
  490.  
  491. void PrintArgList (prog, argv)
  492. String prog;
  493. StringVec argv;
  494. {
  495.     int i;
  496.     
  497.     fprintf(stderr, "%s ", prog);
  498.     for (i=1; argv[i] != 0; i++) {
  499.         fprintf(stderr, "%s ", argv[i]);
  500.     }
  501.     fprintf(stderr,"\n");
  502. }  /* PrintArgList */
  503.  
  504. void initexec (progname)
  505. String progname;
  506. {
  507.     command = commandv;
  508.     *command++ = progname;
  509. }  /* initexec */
  510.  
  511. #if !defined(DOS)
  512. void RedirectIn (in)
  513. FileDesc in;
  514. {
  515.     if (in != stdinDesc) {
  516.         dup2(in, stdinDesc);
  517.         close(in);
  518.     }
  519. }  /* RedirectIn */
  520.  
  521. void RedirectOut (out)
  522. FileDesc out;
  523. {
  524.     if (out != stdoutDesc) {
  525.         dup2(out, stdoutDesc);
  526.         close(out);
  527.     }
  528. }  /* RedirectOut */
  529.  
  530. /*  Special hack to convert vector of string pointers into a
  531.     a simple string for use in NoWaitExec.
  532. */
  533.  
  534. #if defined(M_XENIX)
  535. String makecfxxargs (v)
  536. StringVec v;
  537. {
  538.   static char workstring[256];
  539.   strcpy(workstring, "exec ");
  540.   while (*v != 0) {
  541.     strcat(workstring,*v++);
  542.     strcat(workstring, " ");
  543.   }
  544.   return workstring;
  545. }  /* makecfxxargs */
  546. #endif
  547.  
  548. /* Return pid of child */
  549. int NoWaitExec (name, argv, in, out)
  550. String name;
  551. StringVec argv;
  552. FileDesc in;
  553. FileDesc out;
  554. {
  555.     int pid;
  556.     char *path = "/bin/sh";
  557.     pid=fork();
  558.     if IsChild(pid) {
  559.         RedirectIn(in);
  560.         RedirectOut(out);
  561.                           /* This hack executes cfxx from a shell
  562.                              instead of via execvp.  For some reason
  563.                              cfxx fails if executed from execvp. Sigh.*/
  564. #if defined(M_XENIX)
  565.     if ( name == CCfrontEnd) {
  566.       execl (path, path, "-c", makecfxxargs(argv), (char*)0 );
  567.         }
  568.         else
  569. #endif
  570.         execvp(name, argv);
  571.         fprintf(stderr, "%s: Can not execute %s\n", myname, name);
  572.     perror("CCC: exec error");
  573.         _exit(BADEXEC);
  574.     }
  575.     return pid;
  576. }  /* NoWaitExec */
  577.  
  578. int mywait (pid)
  579. int pid;
  580. {
  581.     int status;
  582.     
  583.     if (pid != -1) {
  584.         while ( wait(&status) != pid ) {
  585.             ;
  586.         }
  587.         if (status != 0) {
  588.             if ((status & 0xff)== 0) {
  589.                 status = status >> 8;
  590.             }
  591.         }
  592.     } else {
  593.         status = -1;
  594.     }
  595.     return status;
  596. }  /* mywait */
  597. #endif 
  598.  
  599. int myexec(name, argv, in, out)
  600. String name;
  601. String argv[];
  602. FileDesc in;
  603. FileDesc out;
  604. {
  605.     int pid, status;
  606. #if !defined(DOS)
  607.     pid = NoWaitExec(name, argv, in, out);
  608.     status = mywait(pid);
  609. #else
  610.     status = spawnvp(P_WAIT, name, argv);
  611. #endif
  612.     return status;
  613. }  /* myexec */
  614.  
  615. /* 
  616.  * If 0 is passed as in or out, use the defaults, stdin and stdout. 
  617.  */
  618. int execute (progfile, argv, in, out) 
  619. String progfile;
  620. StringVec argv;
  621. FileDesc in, out;
  622. {
  623.     int status;
  624.  
  625.     *command++ = nil;              /* Terminate arg list HACK !! */
  626.     if (verboseFlag) {
  627.         PrintArgList(progfile, argv);
  628.     }
  629.     status = 0;
  630.     if (fakeFlag == false) {
  631.         status = myexec(progfile, argv, in, out);
  632.         if (status != 0) {
  633.             numErrors++;
  634.         }
  635.         if (verboseFlag && status != 0) {
  636.             fprintf(stderr,"%s: %s exited with status of %d\n",
  637.                 myname, progfile, status);
  638.         }
  639.     }
  640.  
  641.     return status;
  642. }  /* execute */
  643.  
  644. void NoMoreOpt (opt, arg)
  645. char opt;
  646. String arg;
  647. {
  648.     if (opt != EOL) {
  649.         fprintf(stderr,
  650.             "%s: %c not understood in option %s\n", myname, opt, arg
  651.         );
  652.         Quit(1);
  653.     }
  654. }  /* NoMoreOpt */
  655.  
  656. /****************  This is case_insensitive *****************/
  657. #define TO_UPPER(x) (islower(x) ? toupper(x) : x) 
  658. boolean is_equal (c1, c2)
  659.     char* c1;
  660.     char* c2;
  661. {
  662.   for ( ; *c1 == *c2 || TO_UPPER (*c1) == TO_UPPER (*c2); c1++, c2++)
  663.     if (*c1 == EOL)                   
  664.       return true;                   
  665.   return (*c1 == *c2 || TO_UPPER (*c1) == TO_UPPER (*c2)) ? true : false;
  666. }  /* is_equal */
  667.  
  668. typedef enum 
  669.     {INVALIDFILE, CFILE, CPLUSPLUSFILE, OBJECTFILE,
  670.        ASSEMBLERFILE, LIBRARYFILE, HEADERFILE}
  671.     FileType;
  672.  
  673. struct FileInfo {
  674.     char* suffix;
  675.     FileType type;
  676. };
  677.  
  678. struct FileInfo fileTypeInfo[] = {
  679.     {"C", CPLUSPLUSFILE},
  680.     {"cxx", CPLUSPLUSFILE},
  681.     {"i", CFILE},
  682.     {"c", CFILE},
  683.     {"o", OBJECTFILE},
  684.     {"obj", OBJECTFILE},
  685.     {"s", ASSEMBLERFILE},
  686.     {"asm", ASSEMBLERFILE},
  687.     {"a", LIBRARYFILE},
  688.     {"lib", LIBRARYFILE},
  689.     {"h", HEADERFILE},
  690.     {"hxx", HEADERFILE},
  691.     {EOL, INVALIDFILE}
  692. };
  693.  
  694. /* 
  695.  * dir, tail, ext are VAR parameters
  696.  */
  697. FileType DetermineFileType (filename, dir, tail, ext)
  698. String filename;
  699. String *dir;                              /* Directory */
  700. String *tail;                             /* File name (includes type) */
  701. String *ext;                              /* File type (includes leading .) */
  702. {
  703.   String p;
  704.   FileType kind;
  705.   struct FileInfo *fi;
  706.  
  707.   *dir = nil;                             /* defaults */
  708.   *ext = nil;
  709.   *tail = fileName;
  710.     
  711.   p = strlen(filename) + filename;
  712.   while (p != fileName) {
  713.     if (*p == '.' && *ext == nil) {
  714.       *ext = p;
  715.     } else if (*p == '/' || *p == '\\') {
  716.       *tail = p + 1;
  717.       *p = EOL;
  718.       *dir = fileName;
  719.       break;
  720.     }
  721.     p--;
  722.   }
  723.   /* determine kind of file it is */
  724.   if ( *ext == nil ) {
  725.     kind = LIBRARYFILE;                   /* Assume lib file */
  726.   } else {
  727.     for(fi = fileTypeInfo; fi->suffix != EOL; fi++)
  728. #if defined(DOS)        /* DOS filenames aren't case sensitive */
  729.       if (is_equal((*ext)+1, fi->suffix)) break;
  730. #else
  731.       if (!strcmp((*ext)+1, fi->suffix)) break;
  732. #endif
  733.     kind = fi->type;
  734.   }
  735.   return kind;
  736. }  /* DetermineFileType */
  737.  
  738. void SetUpHandler (sig, handler)
  739. int sig;
  740. void (*handler)();
  741. {
  742. #if defined(DOS)
  743.     int (*signalHandler)();          /* Pointer to integer function */
  744. #else
  745.     void (*signalHandler)();          /* Pointer to integer function */
  746. #endif
  747.     signalHandler = signal(sig, handler);
  748.     if (signalHandler == SIG_IGN) {
  749.         (void) signal(sig, SIG_IGN);
  750.     } else if ((int)signalHandler == -1) {
  751.         perror("CCC: could not set up signal handler");
  752.     }
  753. }  /* SetUpHandler */
  754.  
  755. void interupt ()
  756. {
  757.     RemoveTmpFiles();
  758.     exit(3);
  759. }  /* interupt */
  760.  
  761. void PrintVersionAndPath ()
  762. {
  763.     static boolean printed = false;
  764.     if (printed == false) {
  765.         printf("CCPATH = %s\n", ccPath);
  766.         printed = true;              /* Only print this once */
  767.     }
  768. }  /* PrintVersionAndPath */
  769.  
  770. void HandleArgs (argc, argv)
  771. int argc;
  772. String *argv;
  773. {
  774.     register int i;
  775.     for (i = 1; i < argc; i++) {    /* Handle options of the form '-XXX' */
  776.         if (argv[i][0]==EOL) {        /* Skip null argument */
  777.         } 
  778.         else if (argv[i][0]=='-') {    /* Look at args beginning with - */
  779.             switch (argv[i][1]) {
  780. #if defined(DOS)
  781.                 case 'A':                 /* -Ax select storage model */
  782.                     NoMoreOpt(argv[i][3], argv[i]);
  783.                     ccArgv = AddArg(ccArgv, argv[i]);
  784.                     switch (argv[i][2]) { /* Set default library */
  785.                       case 'S':           /* small */
  786. #if defined(cfront2)
  787.                         StdCClib = "SLcxxe";
  788. #else
  789.                         StdCClib = "SLcxx5ep";
  790. #endif
  791.                         ccArgv = AddArg(ccArgv, "-DM_I86SM");
  792.             cppArgv = AddArg(cppArgv, "-DM_I86SM");
  793.                         break;
  794.                       case 'M':           /* medium */
  795. #if defined(cfront2)
  796.                         StdCClib = "MLcxxe";
  797. #else
  798.                         StdCClib = "MLcxx5ep";
  799. #endif
  800.                         ccArgv = AddArg(ccArgv, "-DM_I86MM");
  801.             cppArgv = AddArg(cppArgv, "-DM_I86MM");
  802.                         frontEndArgv = AddArg(frontEndArgv, "+MM");
  803.                         break;
  804.                       case 'L':           /* large */
  805. #if defined(cfront2)
  806.                         StdCClib = "Lcxxce";
  807. #else
  808.                         StdCClib = "LLcxx5ep";
  809. #endif
  810.                         ccArgv = AddArg(ccArgv, "-DM_I86LM");
  811.             cppArgv = AddArg(cppArgv, "-DM_I86LM");
  812.                         frontEndArgv = AddArg(frontEndArgv, "+ML");
  813.                         break;
  814.                       case 'C':           /* compact */
  815. #if defined(cfront2)
  816.                         StdCClib = "CLcxxe";
  817. #else
  818.                         StdCClib = "CLcxx5ep";
  819. #endif
  820.                         ccArgv = AddArg(ccArgv, "-DM_I86CM");
  821.             cppArgv = AddArg(cppArgv, "-DM_I86CM");
  822.                         frontEndArgv = AddArg(frontEndArgv, "+MC");
  823.                         break;
  824.                       default:
  825.                         NoMoreOpt(argv[i][2], argv[i]);
  826.                     }
  827.                     break;
  828.                 case 'G':                 /* -Gn instruction set */
  829.                     NoMoreOpt(argv[i][3], argv[i]);
  830.                     ccArgv = AddArg(ccArgv, argv[i]);
  831.                     break;
  832.                 case 'Z':                 /* -Zx language extensions */
  833.                     NoMoreOpt(argv[i][3], argv[i]);
  834.                     ccArgv = AddArg(ccArgv, argv[i]);
  835.                     break;
  836.                 case 'g':                 /* -g debug mode */
  837.                     NoMoreOpt(argv[i][2], argv[i]);
  838.                  /* frontEndArgv = AddArg(frontEndArgv, "+L"); */
  839.                     ccArgv = AddArg(ccArgv, "-Zi"); /* include debug info */
  840.                     ccArgv = AddArg(ccArgv, "-Od"); /* turn off optimization */
  841.                     linkArgv = AddArg(linkArgv, "/CO"); /* CodeView link */
  842.                     break;
  843.                 case 'w':                 /* -wn supress warning messages */
  844.                     NoMoreOpt(argv[i][3], argv[i]);
  845.                     ccArgv = AddArg(ccArgv, argv[i]);
  846.                     break;
  847. #endif
  848.                 case 'c':                 /* -c supress linking */
  849.                     cFlag = SET;
  850.                     NoMoreOpt(argv[i][2], argv[i]);
  851.                     break;
  852.                 case 'C':                 /* -C Keep comments */
  853.                     NoMoreOpt(argv[i][2], argv[i]);
  854.                     cppArgv = AddArg(cppArgv, argv[i]);
  855.                     break;
  856.                 case 'd':                 /* -d ??? (passed to cc) */
  857.                     NoMoreOpt(argv[i][2], argv[i]);
  858.                     ccArgv = AddArg(ccArgv, argv[i]);
  859.                     break;
  860.                 case 'E':                 /* -E cpp only */
  861.                     Eflag = SET;
  862.                     NoMoreOpt(argv[i][2], argv[i]);
  863.                     break;
  864.                 case 'F':                 /* -F cpp & cfront only */
  865.                     Fflag = SET;
  866.                     if (argv[i][2] == 'c') { /* -Fc output sutable for cc */
  867.                         NoMoreOpt(argv[i][3], argv[i]);
  868.                         FcFlag = SET;
  869.                     } else {
  870.                         NoMoreOpt(argv[i][2], argv[i]);
  871.                     } /* if */
  872.                     break;
  873.                 case 'i':                 /* added this */
  874.                     ignErrFlag = SET;
  875.                     break;
  876.                 case 'k':                 /* keep __ctdt.c and __ctdt.o */
  877.                     keepctdtFlag = SET;
  878.                     break;
  879.                 case 'l':                 /* -lfile link with library file */
  880.                     strcpy(lastLib, argv[i]+2);
  881. #if defined(DOS)
  882.                     linkLibv = AddArg(linkLibv, argv[i]+2);
  883. #else
  884.                     linkLibv = AddArg(linkLibv, argv[i]);
  885. #endif
  886.                     break;
  887. #if defined(M_XENIX)
  888.                 case 'L':                 /* -L in Xenix handled special */
  889.                     strcpy(libPath, argv[i]+2);
  890.                 break;
  891. #endif
  892.                 case 'N':          /* -NOMUNCH -NOPATCH */
  893.                       /* don't munch/patch result */
  894.                     if (strcmp(argv[i],"-NOMUNCH")==0) {
  895.                         noMunchFlag = SET;
  896.                     } else {
  897.                         ccArgv = AddArg(ccArgv, argv[i]);
  898.                     }
  899.                     break;
  900.                 case 'n':          /* print, but don't do it */
  901.                     NoMoreOpt(argv[i][2], argv[i]);
  902.                     verboseFlag = SET;
  903.                     fakeFlag = SET;
  904.                     PrintVersionAndPath();
  905.                     break;
  906.                 case 'o':                 /* -ofile name of output file */
  907.                     if (argv[i][2] != '\0')
  908.                       strcpy(objName, argv[i]+2);
  909.                     else
  910.                       strcpy(objName, argv[++i]);
  911.                     if (*objName == EOL) {
  912.                         WarningMsg(
  913.                             "No object specified after -o, using a.out", nil);
  914.                     } else {
  915.                         objFlag = SET;
  916. #if !defined(DOS)
  917.                         linkArgv = AddArg(linkArgv, "-o");
  918.                         linkArgv = AddArg(linkArgv, objName);
  919. #endif
  920.                     }
  921.                     break;
  922.                 case 'p':
  923.                     if (argv[i][2] == 'g') { /* -pg gprof*/
  924.                         NoMoreOpt(argv[i][3], argv[i]);
  925.                         gprofFlag = SET;
  926.                         profFlag = false;
  927.                     } else {          /* -p prof */
  928.                         NoMoreOpt(argv[i][2], argv[i]);
  929.                         profFlag = SET;
  930.                         gprofFlag = false;
  931.                     }
  932.                     ccArgv = AddArg(ccArgv, argv[i]);
  933.                     break;
  934.                 case 'r':                 /* -r ??? (passed to cc) */
  935.                     genRelocInfoFlag = SET;
  936.                     NoMoreOpt(argv[i][2], argv[i]);
  937.                     ccArgv = AddArg(ccArgv, argv[i]);
  938.                     break;
  939.                 case 'S':                 /* -S produce assembly source */
  940.                     skipAsmFlag = SET;
  941.                     NoMoreOpt(argv[i][2], argv[i]);
  942.                     ccArgv = AddArg(ccArgv, argv[i]);
  943.                     break;
  944.                 case 'v':          /* -v verbose */
  945.                     verboseFlag = SET;
  946.                     NoMoreOpt(argv[i][2], argv[i]);
  947.                     /* PrintVersionAndPath(); */
  948.                     break;
  949.                 case 'I':                 /* -Ifile include directory */
  950.                     cppArgv = AddArg(cppArgv, argv[i]);
  951.                     break;
  952.                 case 'x':                 /* -xn cpp debug mode */
  953.                 case 'D':                 /* -Dsym define cpp symbol */
  954.                 case 'U':                 /* -Usym undefine cpp symbol */
  955.                     cppArgv = AddArg(cppArgv, argv[i]);
  956.                     break;
  957.                 case '.':                 /* -.suffix suffix for output */
  958.                     if (suffixFlag) {
  959.                         Error("Not allowed to specify more than one suffix", 
  960.                   nil);
  961.                     } /* if */
  962.                     suffixFlag = SET;
  963.                     suffix = &argv[i][1];
  964.                     break;
  965.                 case 'X':                 /*  -X"class<parms>" - implement */
  966.                     Implement(argv[i]+2);
  967.                     break;
  968.                 case 'Q':                 /*  -Q - implement quick */
  969.                     NoMoreOpt(argv[i][2], argv[i]);
  970.                     implementQuick = true;
  971.                     break;
  972.                 default:                  /* Otherwise, send it to cc */
  973.                     ccArgv = AddArg(ccArgv, argv[i]);
  974.                     break;
  975.             }   /* switch (argv[i][1]) */
  976.  
  977.         } else if (argv[i][0] == '/') {   /* /foo options go to the linker */
  978.           linkArgv = AddArg(linkArgv, argv[i]);
  979.           
  980.         } else if (argv[i][0] == '+') {
  981.                     /* handle options of the form '+XXX' */
  982.             switch (argv[i][1]) {
  983.                 case 'd':               /* +d Don't expand inlines */
  984.                     frontEndArgv = AddArg(frontEndArgv, argv[i]);
  985.                     break;
  986.                 case 'e':                 /* +e1 +e0 C++ vtbl generation */
  987.                     frontEndArgv = AddArg(frontEndArgv, argv[i]);
  988.                     break;
  989.                 case 'V':                 /* +V Accept K&R C function decl */
  990.                     NoMoreOpt(argv[i][2], argv[i]);
  991.                     strcpy(libDir, " -I/usr/include");
  992.                     break;
  993.                 case 'L':                 /* +L Use #line instead of # */
  994.                     NoMoreOpt(argv[i][2], argv[i]);
  995.                     break;
  996.                 case 'x':                 /* +xfile Alignment file */
  997.                     if (argv[i][2] != '\0') {
  998.                         frontEndArgv = AddArg(frontEndArgv, argv[i]);
  999.                     } else {
  1000.                         i++;
  1001.                         if (argv[i] == EOL) {
  1002.                             Error("No arg specified after +x", nil);
  1003.                         } else {
  1004.                             strcpy(xBuff, "+x");
  1005.                             strcat(xBuff, argv[i]);
  1006.                             frontEndArgv = AddArg(frontEndArgv, xBuff);
  1007.                         }
  1008.                     }
  1009.                     break;
  1010.                 case 'S':                 /* +S spy on cfront */
  1011.                     NoMoreOpt(argv[i][2], argv[i]);
  1012.                     frontEndArgv = AddArg(frontEndArgv, argv[i]);
  1013.                     break;
  1014.                 case 'i':                 /* +i keep cc source in ..c */
  1015.                     plusIflag = SET;
  1016.                     break;
  1017.                 case 'z':                 /* +zxxx cfront size options */
  1018.                     frontEndArgv = AddArg(frontEndArgv, argv[i]);
  1019.                     break;
  1020.                 default:                  /* otherwise send it to cfront */
  1021.                     frontEndArgv = AddArg(frontEndArgv, argv[i]);
  1022.                     break;
  1023.             }
  1024.         } else {
  1025.             if (processFile(argv[i]) != 0) {
  1026.                 Quit(1);
  1027.             }
  1028.         }
  1029.     }
  1030. }  /* HandleArgs */
  1031.  
  1032. String SetDefaultFromEnv();
  1033. void GetCCPath();
  1034.  
  1035. void Init (envp)
  1036. StringVec envp;
  1037. {
  1038. #if defined(DOS) || defined(MSDOS)
  1039.     PREPROCESSOR = SetDefaultFromEnv(envp, "CCPC=", CC_cpp);
  1040.     CCfrontEnd = SetDefaultFromEnv(envp, "CFRONTC=", CC_compiler);
  1041.     frontEndSuffix = SetDefaultFromEnv(envp, "SUFFIXC=", CC_suffix);
  1042.     StdCClib = SetDefaultFromEnv(envp, "LIBRARY=", CC_library);
  1043.     runtimeLib = SetDefaultFromEnv(envp, "RUNTIMELIBC", CC_rt);
  1044.     translator = (boolean)(strcmp(frontEndSuffix, ".s") != 0);
  1045.     dotdotsuffix = (boolean)(strcmp(frontEndSuffix, "..c") == 0);
  1046.     Ccompiler = SetDefaultFromEnv(envp, "CC=", CC_cc);
  1047.     ASSEMBLER = SetDefaultFromEnv(envp, "ASSEMBLERC=", CC_as);
  1048.     LINKER = SetDefaultFromEnv(envp, "LINKERC=", DEFAULTLINKER);
  1049.     MUNCHER = SetDefaultFromEnv(envp, "MUNCHC=", CC_munch);
  1050.     PATCHER = SetDefaultFromEnv(envp, "PATCHC=", CC_patch);
  1051.     LIB = SetDefaultFromEnv(envp, "LIBC=", CC_lib);
  1052.     TMPDIR = SetDefaultFromEnv(envp, "TMP=", CC_tmp);
  1053.     COMPRESS = SetDefaultFromEnv(envp, "COMPRESS=", CC_compress);
  1054.     MV = SetDefaultFromEnv(envp, "MV=", CC_mv);
  1055. #else
  1056.     PREPROCESSOR = SetDefaultFromEnv(envp, "ccpC=", CC_cpp);
  1057.     CCfrontEnd = SetDefaultFromEnv(envp, "cfrontC=", CC_compiler);
  1058.     frontEndSuffix = SetDefaultFromEnv(envp, "suffixC=", CC_suffix);
  1059.     StdCClib = SetDefaultFromEnv(envp, "LIBRARY=", CC_library);
  1060.     runtimeLib = SetDefaultFromEnv(envp, "runTimeLibC", CC_rt);
  1061.     translator = (boolean)(strcmp(frontEndSuffix, ".s") != 0);
  1062.     dotdotsuffix = (boolean)(strcmp(frontEndSuffix, "..c") == 0);
  1063.     Ccompiler = SetDefaultFromEnv(envp, "ccC=", CC_cc);
  1064.     ASSEMBLER = SetDefaultFromEnv(envp, "assemblerC=", CC_as);
  1065.     LINKER = SetDefaultFromEnv(envp, "linkerC=", DEFAULTLINKER);
  1066.     MUNCHER = SetDefaultFromEnv(envp, "munchC=", CC_munch);
  1067.     PATCHER = SetDefaultFromEnv(envp, "patchC=", CC_patch);
  1068.     LIB = SetDefaultFromEnv(envp, "libC=", CC_lib);
  1069.     TMPDIR = SetDefaultFromEnv(envp, "TMP=", CC_tmp);
  1070.     COMPRESS = SetDefaultFromEnv(envp, "COMPRESS=", CC_compress);
  1071. #endif
  1072.     cclib = "-lc";
  1073.     GetCCPath(environ);
  1074.     ccArgv = AddArgs(ccArgv, CCARGS);
  1075.     frontEndArgv = AddArg(frontEndArgv, CCFRONTARGS);
  1076.     implement_count[0] = '\0';
  1077. }  /* Init */
  1078.  
  1079.  
  1080. int main (argc, argv, envp)
  1081.     int argc;
  1082.     StringVec argv, envp;
  1083. {
  1084.   myname = argv[0];
  1085.   if (argc <= 1) {
  1086.     fprintf(stderr,"usage: %s [options] [ file.{c,o,s} ] \n", myname);
  1087.     exit(-1);
  1088.   }
  1089.   SetUpHandler(SIGINT, interupt);
  1090. #if defined(DOS)
  1091.   SetUpHandler(SIGTERM, interupt);
  1092.   SetUpHandler(SIGBREAK, interupt);
  1093. #else
  1094.   SetUpHandler(SIGQUIT, interupt);
  1095.   SetUpHandler(SIGHUP, interupt);
  1096. #endif
  1097.   Init(envp);
  1098.   HandleArgs(argc, argv);
  1099.   if (objFlag == false) {
  1100.     strcpy(objName, "a.out");
  1101.   }
  1102.   if (numErrors != 0) {
  1103.     Quit(2);
  1104.   }
  1105.   if (Eflag || Fflag || FcFlag || skipAsmFlag) {
  1106.     Quit(0);
  1107.   }
  1108.   if (cFlag) {
  1109.     Quit(0);
  1110.   }
  1111.   Quit(LinkPhase());
  1112. }  /* main */
  1113.  
  1114. #define INCLUDEFLAG "-I"
  1115. #define INCLUDEFLAGLEN 2
  1116.  
  1117. #if defined(DOS)
  1118. #define INCLUDE_SEPERATOR ';'
  1119. #else
  1120. #define INCLUDE_SEPERATOR ':'
  1121. #endif
  1122.  
  1123. void AddIncludes (line)
  1124. String line;
  1125. {
  1126.     String a, b, t;
  1127.     boolean done;
  1128.     
  1129.     if (line == nil) {
  1130.         return;
  1131.     }
  1132.     a = &line[0];
  1133.     b = a;
  1134.     done = false;
  1135.     while (done == false) {
  1136.         done = (boolean) (*b == EOL || *b == '\n' || (b-&line[0]) >= ARGSIZE);
  1137.         if (*b == INCLUDE_SEPERATOR || *b == '\n' || *b == EOL) {
  1138.       if (b>a) {
  1139.             *b = EOL;
  1140.             t = (char *) malloc(b-a + 1 + INCLUDEFLAGLEN);  /* +1=EOL +2=-I */
  1141.             strcpy(t, INCLUDEFLAG);
  1142.             strcat(t, a);
  1143.             cppPathv = AddArg(cppPathv, t);
  1144.             *b = INCLUDE_SEPERATOR;       /* restore so can print ccPath */
  1145.       }
  1146.       a = b+1;
  1147.         }
  1148.         b++;
  1149.     }
  1150. }  /* AddIncludes */
  1151.  
  1152. String ReadEnv (env, pathVar)
  1153. StringVec env;
  1154. String pathVar;
  1155. {
  1156.     int i, len;
  1157.     
  1158.     len = strlen(pathVar);
  1159.     for (i = 0; env[i] != nil; i++) {
  1160.         if (strncmp(env[i], pathVar, len) == 0) {
  1161.             return &env[i][len];
  1162.         }
  1163.     }
  1164.     return nil;
  1165. }  /* ReadEnv */
  1166.  
  1167. String SetDefaultFromEnv (envp, envName, defaultVal)
  1168.     StringVec envp;
  1169.     String envName;
  1170.     String defaultVal;
  1171. {
  1172.   String tmp;
  1173.  
  1174.   tmp = ReadEnv(envp, envName);
  1175.   if (tmp == nil) {
  1176.     tmp = defaultVal;
  1177.   }
  1178.   return tmp;
  1179. }  /* SetDefaultFromEnv */
  1180.  
  1181. void GetCCPath (env)
  1182. StringVec env;
  1183. {
  1184.   String tmp;
  1185.   tmp = ReadEnv(env, ENVPATH);
  1186.   if (tmp != nil) {
  1187.     strcpy(ccPath, tmp);
  1188.     AddIncludes(ccPath);
  1189.   }
  1190. }  /* GetCCPath */
  1191.  
  1192. int Move (filename, oldsuffix, newsuffix)
  1193. String filename, oldsuffix, newsuffix;
  1194. {
  1195.     char aBuffer[FILENAMESIZE], aBuffer2[FILENAMESIZE];
  1196.  
  1197.     strcpy(aBuffer, filename);
  1198.     strcat(aBuffer, oldsuffix);
  1199.     strcpy(aBuffer2, filename);
  1200.     strcat(aBuffer2, newsuffix);
  1201.     return Rename(aBuffer, aBuffer2);
  1202. }  /* Move */
  1203.  
  1204. /* 
  1205.  * process a given file.
  1206.  * either cc, as or just link it. 
  1207.  */
  1208. int processFile (fullPathName)
  1209.     String fullPathName;
  1210. {
  1211.   String dir;                             /* Directory */
  1212.   String fileTail;                        /* File name (includes type) */
  1213.   String ext;                             /* File type (includes leading .) */
  1214.   FileType fileType;
  1215.   int status;
  1216.  
  1217.   linkFile = nil;
  1218.   strcpy(fileName, fullPathName);
  1219.   fileType = DetermineFileType(fileName, &dir, &fileTail, &ext);
  1220.   /*
  1221.    * set linkFile name
  1222.    */
  1223.   if (fileType == CPLUSPLUSFILE ||
  1224.       fileType == ASSEMBLERFILE || 
  1225.       fileType == CFILE) {
  1226.     strcpy(ext, OBJ_Suffix);              /* change xxx.c to xxx.o */
  1227.     linkFile = newString(fileTail);
  1228.  
  1229. /*  Set up to delete the object file if it will be linked. */
  1230.     if (fileType == CPLUSPLUSFILE && cFlag == false) {
  1231.       RegisterTmpFile(linkFile);
  1232.     }
  1233.   } else if (fileType == OBJECTFILE) {
  1234.     linkFile = newString(fullPathName);
  1235.   } else if (fileType == LIBRARYFILE ||
  1236.              fileType == CFILE ||
  1237.              fileType == INVALIDFILE) {
  1238.     linkFile = newString(fullPathName);
  1239.   } else if (fileType == HEADERFILE) {
  1240.     implementArgv = AddArg(implementArgv, fullPathName);
  1241.   }
  1242.   if (ext != nil) {
  1243.     *ext = EOL;                           /* truncate so fileTail has no ext */
  1244.   }
  1245.   /*
  1246.    * set front end name
  1247.    */
  1248.   if (Fflag) {
  1249.     if (suffixFlag) {
  1250.       strcpy(frontEndName, fileTail);
  1251.       strcat(frontEndName, suffix);
  1252.     } else {
  1253.       *frontEndName = EOL;
  1254.     }
  1255.   } else {
  1256.     strcpy(frontEndName, fileTail);
  1257.     strcat(frontEndName, frontEndSuffix);
  1258.   }
  1259.   /*
  1260.    * preprocess, cfront, compile
  1261.    */
  1262.   switch (fileType) {
  1263.   case LIBRARYFILE:
  1264. #if defined(DOS)
  1265.     linkLibv = AddArg(linkLibv, fullPathName);
  1266.     break;
  1267. #endif    
  1268.   case OBJECTFILE:
  1269.   case INVALIDFILE:
  1270.     linkObjv = AddArg(linkObjv, linkFile);
  1271.     return 0;
  1272.   case CPLUSPLUSFILE:
  1273.   case CFILE:
  1274.     linkObjv = AddArg(linkObjv, linkFile);
  1275.     status = CPPphase(fullPathName, fileTail); /* Preprocess */
  1276.     if (Eflag || status != 0) {
  1277.       return status;
  1278.     }
  1279.     return compilePhase(fullPathName, fileTail, fileType); /* Compile */
  1280.   case ASSEMBLERFILE:
  1281.     if (skipAsmFlag == false) {
  1282.       return asmPhase(fullPathName, fileTail); /* Assemble */
  1283.     }
  1284.   }
  1285.   return 0;
  1286. }  /* processFile */
  1287.  
  1288. compilePhase (fullPathName, tail, fileType)
  1289.     String fullPathName;                  /* fullPathname to preprocess */
  1290.     String tail;                          /* file name in fullPathName */
  1291.     FileType fileType;                    /* type of original source   */
  1292. {
  1293.   int status;
  1294.                                           /* translate (cfront) */
  1295.   if (fileType == CPLUSPLUSFILE) {
  1296.     status = FrontEndPhase(fullPathName, frontEndName, cppName);
  1297. /*
  1298. #if defined(DOS) || defined(M_XENIX)
  1299.     TmpFileName(compressName, "cmp", "i");
  1300.     status = FrontEndPhase(fullPathName, compressName, cppName);
  1301. #else
  1302.     status = FrontEndPhase(fullPathName, frontEndName, cppName);
  1303. #endif
  1304. */
  1305.     if (status != 0) {
  1306.       if (plusIflag == false && fileType == CPLUSPLUSFILE) {
  1307.     Remove(frontEndName);
  1308. /*
  1309. #if defined(DOS) || defined(M_XENIX)
  1310.     Remove(compressName);
  1311. #else
  1312.     Remove(frontEndName);
  1313. #endif
  1314. */
  1315.       }
  1316. #if defined(sparc)
  1317.       /* cfront21 on unix creates a .c instead of a ..c file */
  1318.       if (plusIflag && !dotdotsuffix && fileType == CPLUSPLUSFILE)
  1319.     Move(tail, ".c", "..c");
  1320. #endif
  1321.       return status;
  1322.     }
  1323.     Remove(cppName);
  1324.  
  1325.                                           /* Compress output */
  1326. /*
  1327. #if defined(DOS) || defined(M_XENIX)
  1328.     status = CompressPhase(frontEndName, compressName);
  1329.     if (status != 0) {
  1330.       return status;
  1331.     }
  1332.     Remove(compressName);
  1333. #endif
  1334. */
  1335.                                            /* Filter output */
  1336.     if (plusIflag && (Fflag == false || suffixFlag)) {
  1337.       status = FilterPhase(frontEndName, tail);
  1338.       if (status != 0) {
  1339.         return status;
  1340.       }
  1341.     }
  1342.     if (Fflag) {
  1343.       return status;
  1344.     }
  1345.   }                                        /* End frontEnd processing */
  1346.  
  1347.   status = ccPhase(tail, fileType);        /* compile (cc) */
  1348.  
  1349.   if (plusIflag == false && fileType == CPLUSPLUSFILE) {
  1350.     Remove(frontEndName);
  1351.   }
  1352.  
  1353.   if (plusIflag && !dotdotsuffix && fileType == CPLUSPLUSFILE)
  1354.     Move(tail, ".c", "..c");
  1355.  
  1356.   if (status != 0) {
  1357.     return status;
  1358.   }
  1359.  
  1360. #if defined(DOS)
  1361.   if (translator) {
  1362.     return constPhase();          /* constructor (DOS ONLY) */
  1363.   }
  1364. #endif
  1365.  
  1366.   if (dotdotsuffix) {
  1367.     if (skipAsmFlag) {
  1368.       return Move(tail, "..s", ".s");
  1369.     } else {
  1370.       return Move(tail, "..o", OBJ_Suffix);
  1371.     }
  1372.   }
  1373.   return status;
  1374. }  /* compilePhase */
  1375.  
  1376. /*
  1377.  *  The following tranformations are done by '/bin/cc'.
  1378.  *  We have to do them ourselves.
  1379.  *
  1380.  *      '-g'  ==> '-lg' at end of args
  1381.  *      '-pg' ==> '/lib/gcrt0.o'
  1382.  *      '-p'  ==> '/lib/mcrt0.o'
  1383.  */
  1384. int TransformCCArgs () {
  1385.     register int i, j = 0;
  1386.     boolean copy;
  1387.  
  1388.     for (i = 0; i < MAXARGS; i++) {
  1389.         if (ccArgs[i] == 0) {
  1390.             break;
  1391.         }
  1392.         copy = true;
  1393.         if (ccArgs[i][0] == '-') {
  1394.             switch (ccArgs[i][1]) {
  1395.             case 'g':
  1396.                 gFlag = true;
  1397.                 copy = false;
  1398.                 break;
  1399.             case 'p':
  1400.                 if (ccArgs[i][2] == 'g') {
  1401.                     runtimeLib = "/lib/gcrt0.o";
  1402.                 } else {
  1403.                     runtimeLib = "/lib/mcrt0.o";
  1404.                 }
  1405.                 copy = false;
  1406.                 break;
  1407.             }
  1408.         }
  1409.         if (copy) {
  1410.             ccArgs[j++] = ccArgs[i];
  1411.         }
  1412.     }
  1413.     ccArgs[j++] = runtimeLib;
  1414.     while (j < MAXARGS && ccArgs[j] != 0) {
  1415.         ccArgs[j++] = 0;
  1416.     }
  1417. }  /* TransformCCArgs */
  1418.  
  1419. int CPPphase (fullPathName, tail)
  1420.     String fullPathName;                  /* fullPathname to preprocess */
  1421.     String tail;                          /* file name in fullPathName */
  1422. {
  1423.   int status;
  1424.  
  1425.   initexec(PREPROCESSOR);
  1426.   command = AddList(command, cppArgs);
  1427. #if defined(cfront2) || defined(cfront21)
  1428.   command = AddArg(command, "-D__cplusplus=1");  /* for Ansi compatibility */
  1429. #endif
  1430.   command = AddArg(command, "-Dc_plusplus=1");
  1431.   command = AddArg(command, implement_count);
  1432.   command = AddArgs(command, CPPARGS);
  1433.   command = AddList(command, cppPathArgs);
  1434.   if (translator) {
  1435.     command = AddArg(command, libDir);
  1436.   }
  1437.   command = AddArg(command, fullPathName); /* Input file name */
  1438.   if (Eflag) {
  1439.     if (suffixFlag) {
  1440.       strcpy(destname, tail);
  1441.       strcat(destname, suffix);
  1442.       command = AddArg(command, destname); /* output file name */
  1443.     }
  1444.     status = execute(PREPROCESSOR, commandv, stdinDesc, stdoutDesc);
  1445.   } else {
  1446.       TmpFileName(cppName, "cpp", "C");
  1447.       command = AddArg(command, cppName); /* output file name */
  1448.       status = execute(PREPROCESSOR, commandv, stdinDesc, stdoutDesc);
  1449.   }
  1450.   return status;
  1451. }  /* CPPphase */
  1452.  
  1453. int FrontEndPhase (fullPathName, out, in)
  1454.     String fullPathName;
  1455.     String out;
  1456.     String in;
  1457. {
  1458.   int status;
  1459.   char aBuffer[FILENAMESIZE];
  1460.  
  1461.   if (verboseFlag == false) {
  1462.     fprintf(stderr, "C++ Compile: %s\n", fullPathName);
  1463.   }
  1464.  
  1465.   initexec(CCfrontEnd);
  1466.   command = AddList(command, frontEndArgs);
  1467. #if defined(DOS) || defined(M_XENIX)
  1468.   strcpy(aBuffer, "+f");
  1469.   strcat(aBuffer, fullPathName);
  1470.   command = AddArg(command, strdup(aBuffer));
  1471.   strcpy(aBuffer, "+i");
  1472.   strcat(aBuffer, in);
  1473.   command = AddArg(command, strdup(aBuffer));
  1474.   if (*out != EOL) {
  1475.     strcpy(aBuffer, "+o");
  1476.     strcat(aBuffer, out);
  1477.     command = AddArg(command, strdup(aBuffer));
  1478.   }
  1479.  
  1480.   status = execute(CCfrontEnd, commandv,  stdinDesc, stdoutDesc);
  1481.   if (status == 217) {
  1482.     status = 0;                           /* ******** HACK ALERT ********** */
  1483.     numErrors--;
  1484.   }
  1485. #else
  1486.   cppDesc = myopen(in, O_RDONLY, 0644);
  1487.   if (translator) {                       /* cfront */
  1488.     command = AddArg(command, "+L");
  1489.     strcpy(aBuffer, "+f");
  1490.     strcat(aBuffer, fullPathName);
  1491.     command = AddArg(command, strdup(aBuffer));
  1492.  
  1493.  
  1494.   } else {                                /* g++ */
  1495.     command = AddArg(command, "-quiet");
  1496.   }
  1497.   if (Fflag) {
  1498.     if (suffixFlag) {
  1499.       dest = myopen(out, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  1500.       status = execute(CCfrontEnd, commandv, cppDesc, dest);
  1501.       myclose(dest);
  1502.     } else {
  1503.       dest = stdoutDesc;
  1504.       status = execute(CCfrontEnd, commandv, cppDesc, dest);
  1505.     }
  1506.   } else {
  1507.     int frontEndDesc;
  1508.     frontEndDesc = myopen(out, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  1509.     status = execute(CCfrontEnd, commandv, cppDesc, frontEndDesc);
  1510.     myclose(frontEndDesc);
  1511.   }
  1512.   myclose(cppDesc);
  1513. #endif
  1514.   return status;
  1515. }  /* FrontEndPhase */
  1516.  
  1517. int CompressPhase (out, in)
  1518.     String out;
  1519.     String in;
  1520. {
  1521.   int status;
  1522.   initexec(COMPRESS);
  1523.   command = AddArg(command, in);
  1524.   command = AddArg(command, out);
  1525.   status = execute(COMPRESS, commandv, stdinDesc, stdoutDesc);
  1526.   if (status != 0) {
  1527.     WarningMsg(COMPRESS, "error");
  1528.   }
  1529.   return status;
  1530. }  /* CompressPhase */
  1531.  
  1532.  
  1533. /*
  1534.  * Filter out #line directives
  1535.  */
  1536. int FilterPhase (fullPathName, fileTail)
  1537.     String fullPathName;
  1538.     String fileTail;
  1539. {
  1540. #define BUFSIZE 1028
  1541.   int status;
  1542.  
  1543.   if (plusIflag) {
  1544.     register char prev = '\n';
  1545.     char buffer[BUFSIZE];
  1546.     int inDesc;
  1547.     int filterDesc;
  1548.     boolean skip_newline = false;
  1549.  
  1550.     strcpy(filterName, fileTail);
  1551.     strcat(filterName, ".f");
  1552.     filterDesc = myopen(filterName, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  1553.     inDesc = myopen(fullPathName, O_RDONLY, 0644);
  1554.  
  1555.     if (verboseFlag) {
  1556.       fprintf(stderr, "filter %s %s\n", fullPathName, filterName);
  1557.     }
  1558.     if (fakeFlag == false)
  1559.       for (;;) {
  1560.         register char* in = buffer;
  1561.         register char* out = buffer;
  1562.         register char* end = in + read(inDesc, in, BUFSIZE);
  1563.         if (end == in) break;             /* stop at end of file */
  1564.         if (skip_newline) {               /* if skipping at end of prev buf */
  1565.           while (in < end && *in != '\n') in++; /* Skip to new line */
  1566.           prev = *in;
  1567.           skip_newline = false;
  1568.         }
  1569.         while (in < end) {                /* search for \n# */
  1570.           if (prev != '\n' || *in != '#')
  1571.             *out++ = prev = *in++;
  1572.           else {
  1573.             while (in < end && *in != '\n') in++; /* Skip to new line */
  1574.             if (in < end)
  1575.               prev = *in++;
  1576.             else
  1577.               skip_newline = true;
  1578.           }
  1579.         }
  1580.         if (out > buffer)                 /* Write buffer */
  1581.           write(filterDesc, buffer, out - buffer);
  1582.       }
  1583.     myclose(inDesc);
  1584.     myclose(filterDesc);
  1585.     Remove(frontEndName);          /* required by DOS rename command */
  1586.     status = Rename(filterName, frontEndName);
  1587.     if (status != 0) {
  1588.       perror("CCC: error in filter phase");
  1589.     }
  1590.   }
  1591.   return status;
  1592. }  /* FilterPhase */
  1593.  
  1594. int ccPhase (tail, fileType)
  1595.     String tail;
  1596.     FileType fileType;              /* type of original source file */
  1597. {
  1598.   int status;
  1599.   char aBuffer[FILENAMESIZE];
  1600.   char bBuffer[FILENAMESIZE];
  1601.  
  1602.   initexec(Ccompiler);
  1603.   command = AddList(command, ccArgs);
  1604.   command = AddArg(command, "-c");
  1605.  
  1606. #if defined(DOS)
  1607.   command = AddArg(command, "-NM");
  1608.   command = AddArg(command, tail);
  1609.   strcpy(bBuffer, "-Fo");
  1610.   strcat(bBuffer, linkFile);
  1611.   command = AddArg(command, bBuffer);
  1612.   strcpy(aBuffer, "-Tc");
  1613.   strcat(aBuffer, frontEndName);
  1614.   command = AddArg(command, aBuffer);
  1615. #else
  1616.   if (objFlag && cFlag) {
  1617.     command = AddArg(command, "-o");
  1618.     command = AddArg(command, objName);
  1619.   }
  1620.                       /* Allow C files to skip front end */
  1621.   if (fileType == CFILE)
  1622.     command = AddArg(command, cppName);
  1623.   else
  1624.     command = AddArg(command, frontEndName);
  1625. #endif
  1626.  
  1627.   status = execute(Ccompiler, commandv, stdinDesc, stdoutDesc);
  1628.   if (status != 0) {
  1629.     Remove(linkFile);
  1630.   }
  1631.   return status;
  1632. }  /* ccPhase */
  1633.  
  1634. #if defined(DOS) || defined(M_XENIX)
  1635. /*
  1636.  * Implement constructors and destructors for an object file
  1637.  */
  1638. int constPhase ()
  1639. {
  1640.   int status;
  1641.   initexec("mxx");
  1642. #if defined(DOS)
  1643.   command = AddArg(command, "-4");
  1644. #endif
  1645.   command = AddArg(command, linkFile);
  1646.   status = execute("mxx", commandv, stdinDesc, stdoutDesc);
  1647.   return status;
  1648. }  /* constPhase */
  1649. #endif
  1650.  
  1651. int asmPhase (fullPathName, tail)
  1652. String fullPathName, tail;
  1653. {
  1654.     char aBuffer[FILENAMESIZE];
  1655.  
  1656.     initexec(ASSEMBLER);
  1657.     command = AddArg(command, "-o");
  1658.     strcpy(aBuffer, tail);
  1659.     strcat(aBuffer, ".o");          /* out from cc -S */
  1660.     command = AddArg(command, aBuffer);
  1661.     command = AddArg(command, fullPathName);
  1662.     return execute(ASSEMBLER, commandv, stdinDesc, stdoutDesc);
  1663. }  /* asmPhase */
  1664.  
  1665. int RecompileWithMunchPhase ()
  1666. {
  1667.     int status;
  1668.  
  1669.     initexec(Ccompiler);
  1670.     command = AddArg(command, "-c");
  1671.     command = AddArg(command, "__ctdt.c");
  1672.     if (keepctdtFlag == false) {
  1673.         RegisterTmpFile("__ctdt.o");
  1674.     }
  1675.     (void) execute(Ccompiler, commandv, stdinDesc, stdoutDesc);
  1676.     
  1677.     initexec(LINKER);
  1678.     command = AddList(command, ccArgs);
  1679.     command = AddArg(command, "__ctdt.o");
  1680.     command = AddList(command, linkObjs);
  1681.     command = AddList(command, linkArgs);
  1682.     command = AddArg(command, StdCClib);
  1683.     
  1684.     status = execute(LINKER, commandv, stdinDesc, stdoutDesc);
  1685.     return status;
  1686. }  /* RecompileWithMunchPhase */
  1687.  
  1688.  
  1689. int LinkPhase () {
  1690.   int status;
  1691. #if defined(DOS)
  1692.   status = dosLink(DEFAULTLINKER);
  1693. #else
  1694.   if (strcmp(LINKER, INCLINK) == 0) {
  1695.     ccIsLinker = false;
  1696.     status = Inclink();
  1697.   } else {
  1698.     ccIsLinker = true;
  1699.     status = DefaultLink();
  1700.   }
  1701. #endif
  1702.   return status;
  1703. }  /* LinkPhase */
  1704.  
  1705. int Inclink () {
  1706.     TransformCCArgs();
  1707.     return PassOne(RELINK);
  1708. }  /* Inclink */
  1709.  
  1710. int DefaultLink () {
  1711.     int status;
  1712.  
  1713.     if (runtimeLib[0] != '\0') {
  1714.         ccIsLinker = false;
  1715.         TransformCCArgs();
  1716.         linkArgv = AddArg(linkArgv, "-C");
  1717.     }
  1718.     status = PassOne(LINKER);
  1719.     if (translator) {              /* cfront translator */
  1720.       if (status != 0) {
  1721.         return status;
  1722.       }
  1723.       status = PassTwo();
  1724.     }
  1725.     return status;
  1726. }  /* DefaultLink */
  1727.  
  1728. #if defined(DOS)
  1729. int dosLink (linker)
  1730.     char* linker;
  1731. {
  1732.   int status;
  1733.   /* 
  1734.    * format is:
  1735.    *   LINK objects , runfile , listfile , librarylist , options ;
  1736.    */
  1737.   initexec(linker);                       /* LINK */
  1738.   command = AddList(command, linkObjs);   /* objects */
  1739.   command = AddArg(command, ",");
  1740.   if (objFlag) {                          /* runfile */
  1741.     command = AddArg(command, objName);
  1742.   }
  1743.   command = AddArg(command, "/NOIGNORECASE");
  1744.   command = AddArg(command, ",");
  1745.                                           /* listfile */
  1746.   command = AddArg(command, ",");
  1747.   command = AddList(command, linkLibs);   /* librarylist */
  1748.   command = AddArgs(command, StdCClib);
  1749.   command = AddList(command, linkArgs);
  1750.   command = AddArg(command, ";");
  1751.  
  1752.   status = execute(linker, commandv, stdinDesc, stdoutDesc);
  1753.   return status;
  1754. }  /* dosLink */
  1755. #endif
  1756.  
  1757. int PassOne (linker)
  1758.     char* linker;
  1759. {
  1760.   int status;
  1761.  
  1762.   initexec(linker);
  1763.   command = AddList(command, ccArgs);
  1764.   command = AddList(command, linkObjs);
  1765.   command = AddList(command, linkLibs);
  1766. #if defined(InterViews)              /* what is this for??? */ 
  1767.   if (keepctdtFlag)
  1768.     command = AddArg(command, "-k");
  1769. #endif
  1770.   command = AddList(command, linkArgs);
  1771.   command = AddArg(command, StdCClib);
  1772.   if (ccIsLinker == false) {
  1773.     if (gFlag) {
  1774.       command = AddArg(command, "-lg");
  1775.     }
  1776.     command = AddArg(command, cclib);
  1777.     if (linker == RELINK) {
  1778.       command = AddList(command, objSpaceArgs);
  1779.     }
  1780.   }
  1781.   status = execute(linker, commandv, stdinDesc, stdoutDesc);
  1782.   return status;
  1783. }  /* PassOne */
  1784.  
  1785. int PassTwo () {
  1786.   int status;
  1787. #if defined(CC_domunch)
  1788.   status = MunchPhase();
  1789. #else
  1790.   status = PatchPhase();
  1791. #endif
  1792.   return status;
  1793. }  /* PassTwo */
  1794.  
  1795. int PatchPhase () {
  1796.   int status;
  1797.   if (noMunchFlag == false) {
  1798.     initexec(PATCHER);
  1799.     command = AddArg(command, objName);
  1800.     status = execute(PATCHER, commandv, stdinDesc, stdoutDesc);
  1801.   }
  1802.   return status;
  1803. }  /* PatchPhase */
  1804.  
  1805. int MunchPhase () {
  1806.   int status;
  1807.   int nmDesc, munchDesc;
  1808.   char nmName[FILENAMESIZE];
  1809.  
  1810.   if (genRelocInfoFlag  == false && noMunchFlag == false) {
  1811. #if !defined(M_XENIX)
  1812.     nmDesc = MakeTmpFile(nmName, "nm", "txt");
  1813.     initexec("nm");
  1814.     command = AddArg(command, objName);
  1815.     status = execute("/bin/nm", commandv, stdinDesc, nmDesc);
  1816.     if (status != 0) {
  1817.       return status;
  1818.     }
  1819.     close(nmDesc);      
  1820.     close(stdoutDesc);
  1821.     /* input */
  1822.     nmDesc = myopen(nmName, O_RDONLY, 0644);
  1823.     /* output */
  1824.     munchDesc = myopen("__ctdt.c", O_WRONLY | O_CREAT | O_TRUNC, 0644);
  1825.     if (keepctdtFlag == false) {
  1826.       RegisterTmpFile("__ctdt.c");    
  1827.     }
  1828. #endif
  1829.     initexec(MUNCHER);
  1830.     if (profFlag) {
  1831.       command = AddArg(command, "-p");
  1832.     } else if (gprofFlag) {
  1833.       command = AddArg(command, "-pg");
  1834.     }
  1835. #if defined(M_XENIX)
  1836.     command = AddArg(command, objName);
  1837. #endif
  1838.     status = execute(MUNCHER, commandv, nmDesc, munchDesc);
  1839. #if !defined(M_XENIX)
  1840.     if (status != 0) {
  1841.       status = RecompileWithMunchPhase();
  1842.       if (status != 0) {
  1843.         return status;
  1844.       }
  1845.     }
  1846. #endif
  1847.   }
  1848.   return 0;
  1849. }  /* MunchPhase */
  1850.  
  1851. libPhase(fileName) 
  1852.     String fileName;
  1853. {
  1854.   char cmd[100];
  1855.   int status;
  1856.   initexec(LIB);
  1857. #if defined(DOS)
  1858.   sprintf(cmd, "%s -+%s;", lastLib, fileName);
  1859.   command = AddArg(command, cmd);
  1860. #else
  1861.   command = AddArg(command, "rl");
  1862.   command = AddArg(command, lastLib);
  1863.   command = AddArg(command, fileName);
  1864. #endif
  1865.   status = execute(LIB, commandv, stdinDesc, stdoutDesc);         
  1866.   return status;
  1867. }  /* libPhase */
  1868.  
  1869. Implement(what)
  1870.     String what;
  1871. {
  1872.   int status;
  1873.   int i;
  1874.   StringVec argv = implementArgs;
  1875.   FILE* implementfile;
  1876.   if (*what == EOL)
  1877.     Error ("You must specify \"class<parms>\" to implement with the -X option",
  1878.        NULL);
  1879.   if (*objName == EOL)
  1880.     Error ("When using -X, you must specify an object name with the -o option",
  1881.        NULL);
  1882.   if (*lastLib == EOL)
  1883.     Error ("When using -X, you must specify a library name with the -l option",
  1884.        NULL);
  1885.   objFlag = false;
  1886.   TmpFileName(implementName, "imp", "C");
  1887.   implementfile = fopen(implementName, "w");
  1888.   fprintf(implementfile, "// CCC implementation input file\n");
  1889.   for (i=0; argv[i] != 0; i++)
  1890.     fprintf(implementfile, "#include <%s>\n", argv[i]);
  1891.   Eflag = false;                          /* Disable the -E option */
  1892.   cFlag = SET;                            /* Don't try to link */
  1893.   /*
  1894.    * Check for the fast track - a single compile
  1895.    */
  1896.   if (implementQuick) {
  1897.     char* what_name = strdup(what);
  1898.     char* p = strchr(what_name, '<');
  1899.     sprintf(frontEndName, "%s%s", objName, frontEndSuffix);
  1900.     if (p != NULL) *p = '\0';     /* Get the name of the class to implement */
  1901.     fprintf(implementfile,
  1902.             "#pragma defmacro IMPLEMENT_1 implement delimiter=> lines %s\n",
  1903.             what_name);
  1904.     fprintf(implementfile, "IMPLEMENT_1 %s\n", what);
  1905.     fclose(implementfile);
  1906.     linkFile = newString(objName);
  1907.     strcat(linkFile, OBJ_Suffix);
  1908.     /* Preprocess */
  1909.     status = CPPphase(implementName, objName);
  1910.     if (status != 0) return status;
  1911.     status = compilePhase(implementName, objName, CPLUSPLUSFILE);
  1912.     Remove(implementName);    
  1913.     libPhase(linkFile);
  1914.     Remove(linkFile);
  1915.   } else {
  1916.     int count;
  1917.     fprintf(implementfile,
  1918.         "#pragma defmacro IMPLEMENT_N implement_n delimiter=> lines\n");
  1919.     fprintf(implementfile, 
  1920.    "#pragma defmacro DECLARE_ONCE declare_once delimiter=> recursive lines\n");
  1921.     fprintf(implementfile, "DECLARE_ONCE %s\n", what);
  1922.     fprintf(implementfile, "MACRO EXPANDING EXPAND_IMPLEMENT(count)\n");
  1923.     fprintf(implementfile, "{IMPLEMENT_N count %s}\n", what);
  1924.     fprintf(implementfile, "EXPAND_IMPLEMENT(Count)\n");
  1925.     fclose(implementfile);
  1926.     linkFile = newString(objName);
  1927.     if (strlen(objName) > 7) objName[7] = '\0';
  1928.     for(count=0;;count++) {
  1929.       char newImpName[FILENAMESIZE];
  1930.       char moduleName[FILENAMESIZE];
  1931.       if (strlen(objName) > 6 && count > 9) objName[6] = '\0';
  1932.       sprintf(frontEndName, "%s%d%s", objName, count, frontEndSuffix);
  1933.       sprintf(linkFile, "%s%d%s", objName, count, OBJ_Suffix);
  1934.       sprintf(moduleName, "%s%d", objName, count);
  1935.       sprintf(newImpName, "%s%s.%s", TMPDIR, moduleName, "C");
  1936.       sprintf(implement_count, "-DCount=%d", count);
  1937.       Rename(implementName,newImpName);
  1938.       status = CPPphase(newImpName, objName);
  1939.       if (status != 0) break;
  1940.       status = compilePhase(newImpName, moduleName, CPLUSPLUSFILE);
  1941.       libPhase(linkFile);
  1942.       Remove(linkFile);
  1943.       strcpy(implementName,newImpName);
  1944.     }
  1945.     if (count > 0) {
  1946.       numErrors--;                        /* We expect 1 error from cpp */
  1947.       status = 0;
  1948.     }
  1949.     Remove(implementName);    
  1950.   }    
  1951.   return status;
  1952. }  /* Implement */
  1953.